package uk.co.entropedia.display
{
	import com.bit101.components.ComboBox;
	import com.bit101.components.Component;
	import com.bit101.components.HBox;
	import com.bit101.components.InputText;
	import com.bit101.components.Label;
	import com.bit101.components.Panel;
	import com.bit101.components.PushButton;
	import com.bit101.components.VBox;
	import com.bit101.components.VUISlider;
	import com.bit101.components.Window;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	
	public class DialogComponent extends Window implements IDialogComponentEditor
	{
		protected var _target : Component;
		protected var dialogParentSelect : ComboBox;
		protected var topComponent : Component;
		
		protected var margin : Number = 5;

		public function DialogComponent(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, topComponent : Component = null, title:String="Edit Component" )
		{
			this.topComponent = topComponent;
			
			super(parent, xpos, ypos, title);
			hasCloseButton = true;
			
			setSize(200,120);
			
			var dialogLayout : VBox = new VBox( this, margin, margin );
			dialogLayout.setSize( width-margin,height-margin);
			new Label(dialogLayout,0,0,'Component parent');
			dialogParentSelect = new ComboBox( dialogLayout, 0, 0, 'parent', ( topComponent ) ? getContainerComponents( topComponent ) : null );
			new PushButton( dialogLayout, 0, 0, 'Delete', handleDeleteClick );
			
			
			this.visible = false;
			addEventListener( Event.CLOSE, handleClose );
			
		}
		
		public function set target(value:Component):void
		{
			dialogParentSelect.removeEventListener( Event.SELECT, handleChange );
			_target = value as Component;
			
			var componentNameList : Array = getContainerComponents( topComponent, value ).map(function(c:Component,i:int,a:Array):Object{ return { label : c.name, component : c } });
			dialogParentSelect.items = ( _target ) ? componentNameList : [] ;
			dialogParentSelect.selectedItem = ( _target ) ? nextContainerComponent( value.parent ) : null ;
			
			visible = ( _target is Component ) && ( dialogParentSelect.items.length > 0 );
			if( visible ) dialogParentSelect.addEventListener( Event.SELECT, handleChange );			

		}
		
		public function get target():Component
		{
			return _target;
		}
		
		protected function handleChange(e:Event):void
		{
			if( ! dialogParentSelect.selectedItem ) return ;
			var newParent : Component = ( dialogParentSelect.selectedItem.component  as Component );
			if( newParent && _target )
			{
				/**
				  * O'Mighty Code Gods please forgive the following
				  * Horrible Horrible Horribleness
				  *  
				  * It's 23:23 at night, I'm tired, and my TV
				  * is on some god awful American Teenage sitcom
				 **/
				
				_target.move(0,0);
				newParent.addChild( _target );
				_target.move(0,0);
				newParent.addChild( _target );
				_target.draw();
			}
			
			dispatchEvent( new Event( Event.CHANGE, true ) );
		}
		
		protected function handleClose(e:Event):void
		{
			visible = false;
		}
		
		protected function handleDeleteClick(e:Event):void
		{
			target.parent.removeChild( target );
			target = null;
		}
		
		public static function getContainerComponents( parent : DisplayObjectContainer, eliminateBranch : Component = null ):Array
		{
			var out : Array = [];
			if( parent == eliminateBranch ) return out;
			
			if( isContainerComponent( parent ) ) out.push( parent );
			
			for( var i : int = 0 ; i < parent.numChildren ; i++ )
			{
				var d : DisplayObject = parent.getChildAt( i );
				if( d is DisplayObjectContainer ) out = out.concat( getContainerComponents( d as DisplayObjectContainer, eliminateBranch ) );
			}
			
			return out;
		}
		
		public static function nextContainerComponent( c : DisplayObject ):Component
		{
			if( ! c ) return null;
			var container : DisplayObject = c;
			while( container && ! ( isContainerComponent( container ) ) ) container = container.parent;
			return container as Component;
		}

		public static function nextComponent( c : DisplayObject ):Component
		{
			if( ! c ) return null;
			var container : DisplayObject = c;
			while( container && !isComponent(container) ) container = container.parent;
			return container as Component;
		}
		
		public static function isComponent( d : DisplayObject ):Boolean
		{
			return ( d is Component ) && Component( d ).tag >= 0;
		}
		
		public static function isContainerComponent( d : DisplayObject ):Boolean
		{
			return asContainerComponent( d ) is Component && Component( d ).tag >= 0;
		}
		
		public static function asContainerComponent( d : DisplayObject ):Component
		{
			return ( d as HBox ) || ( d as VBox ) || ( d as Panel ) || ( d as Window );
		}
	}
}